package demo.message;

import demo.storage.LogEntry;
import java.util.List;
import java.io.Serializable;

/**
 * Raft消息类，包含所有RPC消息类型
 */
public class RaftMessage {
    
    /**
     * 请求投票RPC请求
     */
    public static class VoteRequest implements Serializable {
        private final int term;           // 候选人的任期号
        private final String senderId;    // 发送者ID
        private final String candidateId; // 请求选票的候选人ID
        private final int lastLogIndex;   // 候选人的最后日志条目的索引值
        private final int lastLogTerm;    // 候选人最后日志条目的任期号
        
        public VoteRequest(int term, String senderId, String candidateId, int lastLogIndex, int lastLogTerm) {
            this.term = term;
            this.senderId = senderId;
            this.candidateId = candidateId;
            this.lastLogIndex = lastLogIndex;
            this.lastLogTerm = lastLogTerm;
        }
        
        public int getTerm() { return term; }
        public String getSenderId() { return senderId; }
        public String getCandidateId() { return candidateId; }
        public int getLastLogIndex() { return lastLogIndex; }
        public int getLastLogTerm() { return lastLogTerm; }
    }
    
    /**
     * 请求投票RPC响应
     */
    public static class VoteResponse implements Serializable {
        private final int term;           // 当前任期号，以便于候选人去更新自己的任期号
        private final String senderId;    // 发送者ID
        private final String candidateId; // 候选人ID
        private final boolean granted;    // 是否投票给候选人
        
        public VoteResponse(int term, String senderId, String candidateId, boolean granted) {
            this.term = term;
            this.senderId = senderId;
            this.candidateId = candidateId;
            this.granted = granted;
        }
        
        public int getTerm() { return term; }
        public String getSenderId() { return senderId; }
        public String getCandidateId() { return candidateId; }
        public boolean isGranted() { return granted; }
    }
    
    /**
     * 附加日志RPC请求
     */
    public static class AppendEntriesRequest implements Serializable {
        private final int term;             // 领导人的任期号
        private final String senderId;      // 发送者ID
        private final String leaderId;      // 领导人ID
        private final int prevLogIndex;     // 新的日志条目紧随之前的索引值
        private final int prevLogTerm;      // prevLogIndex条目的任期号
        private final List<LogEntry> entries; // 准备存储的日志条目（表示心跳时为空）
        private final int leaderCommit;     // 领导人已经提交的日志的索引值
        
        public AppendEntriesRequest(int term, String senderId, String leaderId, int prevLogIndex, 
                                  int prevLogTerm, List<LogEntry> entries, int leaderCommit) {
            this.term = term;
            this.senderId = senderId;
            this.leaderId = leaderId;
            this.prevLogIndex = prevLogIndex;
            this.prevLogTerm = prevLogTerm;
            this.entries = entries;
            this.leaderCommit = leaderCommit;
        }
        
        public int getTerm() { return term; }
        public String getSenderId() { return senderId; }
        public String getLeaderId() { return leaderId; }
        public int getPrevLogIndex() { return prevLogIndex; }
        public int getPrevLogTerm() { return prevLogTerm; }
        public List<LogEntry> getEntries() { return entries; }
        public int getLeaderCommit() { return leaderCommit; }
    }
    
    /**
     * 附加日志RPC响应
     */
    public static class AppendEntriesResponse implements Serializable {
        private final int term;           // 当前任期号，用于领导人去更新自己
        private final String senderId;    // 发送者ID
        private final String leaderId;    // 领导人ID
        private final boolean success;    // 如果跟随者包含了匹配上prevLogIndex和prevLogTerm的日志时为真
        private final int lastLogIndex;   // 跟随者的最后日志条目的索引值
        
        public AppendEntriesResponse(int term, String senderId, String leaderId, boolean success, int lastLogIndex) {
            this.term = term;
            this.senderId = senderId;
            this.leaderId = leaderId;
            this.success = success;
            this.lastLogIndex = lastLogIndex;
        }
        
        public int getTerm() { return term; }
        public String getSenderId() { return senderId; }
        public String getLeaderId() { return leaderId; }
        public boolean isSuccess() { return success; }
        public int getLastLogIndex() { return lastLogIndex; }
    }
}